﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Profile;
using System.Web.Routing;
using System.Web.Security;

using DotNetOpenAuth.OpenId.RelyingParty;

using P5.OpenIdEx;
using P5.OpenIdEx.Objects;

using P5.TestUsingOpenId.Models;
using P5.MembershipEx;
using P5.MembershipEx.Objects;

namespace P5.TestUsingOpenId.Controllers
{

    [HandleError]
    public class AccountController : Controller
    {

        public IFormsAuthenticationService FormsService { get; set; }
        public IMembershipService MembershipService { get; set; }

        protected override void Initialize(RequestContext requestContext)
        {
            if (this.FormsService == null)
            {
                this.FormsService = new FormsAuthenticationService();
            }
            if (this.MembershipService == null)
            {
                this.MembershipService = new AccountMembershipService();
            }

            base.Initialize(requestContext);
        }

        // **************************************
        // URL: /Account/LogOn
        // **************************************

        public ActionResult LogOn()
        {
            LogOnModel localLogOnModel = new LogOnModel();

            if (base.Request.QueryString["p"] != null)
            {
                OpenIdAccountInfo accountInfo;
                OpenIdRelyingParty openIdRelyingParty;
                bool authenticatedResult = OpenIdHelper.GetOpenIdResponseInfo(out openIdRelyingParty, out accountInfo);

                localLogOnModel.IsUsingOpenId = true;
                localLogOnModel.IsAuthenticated = authenticatedResult;

                if (authenticatedResult)
                {
                    base.Session[OpenIdProviders.SESSION_ACCOUNT_INFO] = accountInfo;
                    MembershipUser userInfo = this.MembershipService.GetUser(accountInfo.ClaimedIdentifier);

                    if (userInfo == null)
                    {
                        return base.RedirectToAction("RegisterOpenId");
                    }
                    else
                    {
                        this.FormsService.SignIn(accountInfo.ClaimedIdentifier, false);
                        return base.RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    string suppliedProvider = base.Request.QueryString["p"].ToString();
                    string suppliedIdentifier;

                    switch (suppliedProvider.Trim())
                    {
                        case OpenIdProviders.GOOGLE:
                            suppliedIdentifier = OpenIdProviders.GOOGLE_IDENTIFIER;
                            break;
                        case OpenIdProviders.YAHOO:
                            suppliedIdentifier = OpenIdProviders.YAHOO_IDENTIFIER;
                            break;
                        case OpenIdProviders.MYOPENID:
                            suppliedIdentifier = OpenIdProviders.MYOPENID_IDENTIFIER;
                            break;
                        default:
                            suppliedIdentifier = string.Empty;
                            break;
                    }

                    if (!string.IsNullOrEmpty(suppliedIdentifier))
                    {
                        OpenIdHelper.RedirectToProvider(openIdRelyingParty, suppliedIdentifier);
                    }
                }
            }

            return View();
        }

        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ValidateUser(model.UserName, model.Password))
                {
                    FormsService.SignIn(model.UserName, model.RememberMe);
                    if (!String.IsNullOrEmpty(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "The user name or password provided is incorrect.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        // **************************************
        // URL: /Account/LogOff
        // **************************************

        public ActionResult LogOff()
        {
            base.Session.Clear();
            this.FormsService.SignOut();

            return base.RedirectToAction("Index", "Home");
        }

        // **************************************
        // URL: /Account/Register
        // **************************************

        public ActionResult Register()
        {
            base.ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            base.ViewData["Provinces"] = this.GetProvinces(Guid.Empty);

            return base.View("Register");
        }

        private SelectList GetProvinces(Guid selectedProvinceId)
        {
            List<Province> provinces = new List<Province>();
            provinces.Add(new Province
            {
                Id = Guid.Empty,
                Name = "[ Select One ]"
            });
            provinces.Add(new Province
            {
                Id = Guid.NewGuid(),
                Name = "Hanoi"
            });
            provinces.Add(new Province
            {
                Id = Guid.NewGuid(),
                Name = "Hai Phong"
            });
            provinces.Add(new Province
            {
                Id = Guid.NewGuid(),
                Name = "Hai Duong"
            });

            Province selectedProvinceObj = provinces.Find(delegate(Province p) { return p.Id == selectedProvinceId; });
            return new SelectList(provinces, "Id", "Name", selectedProvinceObj);
        }

        public ActionResult RegisterOpenId()
        {
            OpenIdAccountInfo accountInfo = base.Session[OpenIdProviders.SESSION_ACCOUNT_INFO] as OpenIdAccountInfo;
            if (accountInfo != null)
            {
                MembershipCreateStatus createStatus = this.MembershipService.CreateUser(accountInfo.ClaimedIdentifier, "Nothing", accountInfo.EmailAddress);
                if (createStatus != MembershipCreateStatus.Success)
                {
                    base.ModelState.AddModelError("MembershipCreateStatus", AccountValidation.ErrorCodeToString(createStatus));
                }
            }

            OpenIdRegisterModel localRegisterModel = new OpenIdRegisterModel();
            localRegisterModel.UserName = accountInfo.ClaimedIdentifier;
            localRegisterModel.AuthenticatedUserInfo = accountInfo;

            return base.View(localRegisterModel);
        }

        [HttpPost]
        public ActionResult RegisterOpenId(OpenIdRegisterModel model)
        {
            if (base.ModelState.IsValid)
            {
                OpenIdAccountInfo accountInfo = base.Session[OpenIdProviders.SESSION_ACCOUNT_INFO] as OpenIdAccountInfo;

                MembershipUser currentUser = this.MembershipService.GetUser(accountInfo.ClaimedIdentifier);
                currentUser.Email = model.Email;

                this.MembershipService.UpdateUser(currentUser);
                this.FormsService.SignIn(model.UserName, false);

                CustomMvcProfile p = base.HttpContext.Profile as CustomMvcProfile;
                p.Initialize(model.UserName, true);
                p.BasicInformation = new CommonInformation();
                p.BasicInformation.FullName = "HuanHV";
                p.BasicInformation.Gender = "F";
                p.BasicInformation.Birthday = DateTime.MinValue;
                p.Save();

                return RedirectToAction("Index", "Home");
            }

            return base.View(model);
        }

        [HttpPost]
        public ActionResult Register(RegisterModel model, FormCollection formCollection)
        {
            if (model.ProvinceId == Guid.Empty)
            {
                ModelState.AddModelError("ProvinceId", "You must select a province.");
            }

            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
                }
            }

            // If we got this far, something failed, redisplay form
            base.ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            base.ViewData["Provinces"] = this.GetProvinces(model.ProvinceId);

            return View(model);
        }

        // **************************************
        // URL: /Account/ChangePassword
        // **************************************

        [Authorize]
        public ActionResult ChangePassword()
        {
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                {
                    return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                }
            }

            // If we got this far, something failed, redisplay form
            ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
            return View(model);
        }

        // **************************************
        // URL: /Account/ChangePasswordSuccess
        // **************************************

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

    }
}
